package com.ruoyi.Factory.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.ruoyi.Factory.domain.General;
import com.ruoyi.Factory.mapper.GeneralMapper;
import com.ruoyi.Factory.service.GeneralService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Validator;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class GeneralServiceImpl implements GeneralService {

    @Autowired
    private GeneralMapper generalMapper;

    @Autowired
    protected Validator validator;

    @Override
    public List<General> selectGeneralList(General general,String table) {
        return generalMapper.selectGeneralList(general,table);
    }

    @Override
    public General selectGeneralById(Long id,String table) {
        return generalMapper.selectGeneralById(id,table);
    }

    @Override
    public int insertGeneral(General general,String table) {
        return generalMapper.insertGeneral(general,table);
    }

    @Override
    public int updateGeneral(General general,String table) {
        return generalMapper.updateGeneral(general,table);
    }

    @Override
    public int deleteGeneralByIds(List<Long> ids,String table) {
        return generalMapper.deleteGeneralByIds(ids,table);
    }

    @Override
    public int ClearGeneral(String table) {
        return generalMapper.ClearGeneral(table);
    }

    @Override
    public List<General> selectGeneralByIds(Long[] ids,String table) {
        return generalMapper.selectGeneralByIds(ids,table);
    }

    @SneakyThrows
    @Override
    public void exportByTemplate1(List<General> list,HttpServletResponse response) {
        int i=1;
        for (General general:list){
            String sjNumber = general.getSjNumber();
            String[] parts =sjNumber.split("-");
            if (parts.length>1){
                general.setSjNumber(parts[0]);
                general.setElectrodeForm(parts[1]);
            }
            general.setId(i);
            i++;
        }
        exportExcel(list,response,"templates.excel/MB2000-R1.xlsx",null);
        exportExcel(list,response,"templates.excel/商科参数模板.xlsx",null);
    }

    @SneakyThrows
    @Override
    public void exportByTemplate2(List<General> list, HttpServletResponse response) {
        // 填充固定值
        List<Map<String, Object>> fixedValues = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> Values = new HashMap<>();
            // 假设固定值需要填充到占位符 {{fixedValue}}
            Values.put("fixedValue", 1);
            Values.put("index", i + 1);
            fixedValues.add(Values);
        }
        exportExcel(list,response,"templates.excel/点焊专项验证报告+验证记录+问题清单.xlsx",fixedValues);
    }

    private void exportExcel(List<General> list, HttpServletResponse response,String templatePath, List<Map<String, Object>>fixedMap)throws Exception{

        // 文件模板输入流，将 excel 模板放到 resources 目录下
        InputStream templateFile = new ClassPathResource(templatePath).getInputStream();
        try(ServletOutputStream out = response.getOutputStream();
            ExcelWriter writer = EasyExcel.write(out)
                    .withTemplate(templateFile)
                    .build()){

            WriteSheet sheet = EasyExcel.writerSheet().build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
            // 填充列表占位符
            writer.fill(list, fillConfig, sheet);

            if (fixedMap != null && !fixedMap.isEmpty()){
                writer.fill(fixedMap, fillConfig, sheet);
            }
        }
    }


    @Override
    public String importGeneral(List<General> generalList,String table) {
        if (StringUtils.isNull(generalList) || generalList.isEmpty()) {
            throw new ServiceException("导入数据不能为空！");
        }
        generalList.forEach(this::stripSlash);
        int total = generalList.size();
        try {
            generalMapper.insertBatch(generalList,table);
        }catch (Exception e){
            return insertOneByOne(generalList,table);
        }
        return "数据批量导入成功！共："+total+"条";
    }
    private String insertOneByOne(List<General> generalList,String table){
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (General general : generalList) {
            try {
                generalMapper.insertGeneral(general,table);
                successNum++;
                successMsg.append("<br/>" )
                        .append( successNum)
                        .append("、数据General ")
                        .append(" 导入成功");

            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>" )
                        .append(failureNum)
                        .append("、数据General ")
                        .append(" 导入失败");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "数据逐条导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "数据逐条导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
    private void stripSlash(General general) {
        Field[] fields = general.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                if (f.getType() == String.class) {
                    String old = (String) f.get(general);
                    if (old != null) {
                        String cleaned = old.replace("\\", "")
                                .replace("＼", "")
                                .replace("#N/A","");
                        f.set(general, cleaned);
                    }
                }
            } catch (IllegalAccessException ignored) {
                // 忽略无法访问的字段
            }
        }
    }

    public static Map<String,List<General>> versionComparison(List<General> list1,List<General> list2){

        Map<String,General> map1 = list1.stream().collect(Collectors.toMap(General::getSjNumber, t->t,(o1, o2) -> o1));
        Map<String,General> map2 = list2.stream().collect(Collectors.toMap(General::getSjNumber, t->t,(o1, o2) -> o1));
        List<General> only1 = new ArrayList<>();
        List<General> only2 = new ArrayList<>();
        List<General> both = new ArrayList<>();
        map1.forEach((k,v) -> {
            if (map2.containsKey(k)) both.add(v);
            else only1.add(v);
        });
        map2.forEach((k,v) -> {
            if (map1.containsKey(k)) both.add(v);
            else only2.add(v);
        });
        Map<String, List<General>> groups = both.stream()
                .collect(Collectors.groupingBy(GeneralServiceImpl::buildBizKey));

        List<General> dedupBoth = groups.values().stream()
                .filter(list -> list.size() != 2) // 不是恰好两条就保留
                .flatMap(List::stream)
                .collect(Collectors.toList());

        Map<String,List<General>> generalMap = new HashMap<>();
        generalMap.put("多",only1);
        generalMap.put("少",only2);
        generalMap.put("变化",dedupBoth);

     return generalMap;
    }

    /* ====== 1. 生成业务键（除 newVersion 外所有 getter 值） ====== */
    private static String buildBizKey(General g) {
        return Arrays.stream(g.getClass().getMethods()) // 含父类 public getter
                .filter(m -> m.getName().startsWith("get"))
                .filter(m -> !(m.getName().equals("getNewVersion")||m.getName().equals("getId")))
                .filter(m -> m.getParameterCount() == 0)
                .sorted(Comparator.comparing(Method::getName))
                .map(m -> invoke(g, m))          // 传入当前对象 g
                .collect(Collectors.joining("|"));
    }

    private static String invoke(General g, Method m) {
        try { return String.valueOf(m.invoke(g)); }
        catch (Exception e) { throw new RuntimeException(e); }
    }

}
